/*
===========================================================================
This source file is part of DyLab (Dynamic Laboratory)
For the latest info, see http://dylab-modules.googlecode.com

Copyright (c) 2006-2008 Lukas Krejci
(krejci.lukas@volny.cz)

This file is part of DyLab.

    DyLab is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DyLab is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with DyLab.  If not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/

//===========================================================================================
#include "Ogre_Gfx.h"

//===========================================================================================
dylab::Ogre_Gfx::ObjectPool::ObjectPool(const String & _name, IScene * _scene, uint32_t _maxObjects)
: mName(_name), mParentScene(_scene), mMaxObjects(_maxObjects)
{
    DYLAB_ASSERT(mParentScene != NULL);

    // fill the stack with available generated object names
    for (uint32_t i = 0; i < mMaxObjects; i++)
    {
        String objName = String::fmt("%1%.object%2%", mName, i);
        mFreeNames.push(objName);
    }
}
//-----------------------------------------------------------------------------
dylab::Ogre_Gfx::ObjectPool::~ObjectPool()
{
    // destroy all objects created in the scene
    for (CreatedObjectNames::Iterator objName(mCreatedObjectNames); objName.isValid(); objName++)    
        mParentScene->destroyObject(objName());
}
//-----------------------------------------------------------------------------
dylab::String dylab::Ogre_Gfx::ObjectPool::getName() const
{
    return mName;
}
//-----------------------------------------------------------------------------
dylab::Ogre_Gfx::IObject *
dylab::Ogre_Gfx::ObjectPool::newObject(const String & _name)
{   
    if (mFreeNames.isEmpty())
    {
        DYLAB_TRACEF3("Unable to create new object '%1%' from pool '%3%'. Reached maximum object limit (%2%)", _name, mMaxObjects, mName);
        return NULL;
    }

    // get next free name // move it to the used names stack
    String objName = mFreeNames.top(); 

    // move it to the used names stack
    mFreeNames.pop();
    mUsedNames.insert(objName, objName);

    // if the user has specified the object name, then insert it into the map
    if (!_name.isEmpty())
        mCustomNamesMap.insert(_name, objName);

    // try to find the object
    IObject * obj = mParentScene->findObject(objName);

    // if does not exists, create a new one
    if (obj == NULL)
    {
        obj = mParentScene->createObject(objName);
        mCreatedObjectNames.insertAtEnd(objName);
    }
    else
    {
        dynamicCast<Object>(obj)->getOgreManualObject()->setVisible(true);
    }

    // return the object
    return obj;
}
//-----------------------------------------------------------------------------
dylab::Ogre_Gfx::IObject * 
dylab::Ogre_Gfx::ObjectPool::getObject(const String & _name)
{
    return mParentScene->getObject(mCustomNamesMap.get(_name));
}
//-----------------------------------------------------------------------------
const dylab::Ogre_Gfx::IObject * 
dylab::Ogre_Gfx::ObjectPool::getObject(const String & _name) const
{
    return mParentScene->getObject(mCustomNamesMap.get(_name));
}
//-----------------------------------------------------------------------------
void dylab::Ogre_Gfx::ObjectPool::deleteObject(const String & _name)
{
    String objName = mCustomNamesMap.get(_name);
    Ogre::ManualObject * obj = dynamicCast<Object>(mParentScene->getObject(objName))->getOgreManualObject();
    obj->clear();
    obj->getParentSceneNode()->setVisible(false);
    mUsedNames.remove(objName);
    mFreeNames.push(objName);
}
//-----------------------------------------------------------------------------
void dylab::Ogre_Gfx::ObjectPool::deleteAllObjects()
{
    // "delete" all used object
    for (UsedNames::Iterator objName(mUsedNames); objName.isValid(); objName++)
    {
        Ogre::ManualObject * obj = dynamicCast<Object>(mParentScene->getObject(objName))->getOgreManualObject();
        obj->clear();
        obj->getParentSceneNode()->setVisible(false);
        mFreeNames.push(~objName);
    }
    mUsedNames.removeAll();
}
//-----------------------------------------------------------------------------